package com.fi.common.domain.vo;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.fi.recogn.dto.table.Cell;
import com.fi.recogn.dto.table.Line;
import com.fi.recogn.dto.table.Table;
import com.fi.recogn.enums.ExcelOcrTypeEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import static com.fi.recogn.enums.ExcelOcrTypeEnum.PLAIN;
import static com.fi.recogn.enums.ExcelOcrTypeEnum.TABLE_WITH_LINE;

/**
 * @Description TODO word 元数据信息
 * @Author lujiahong
 * @Date 2024/8/12 17:50
 */
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class FileDataHtml extends FileData{

    private String htmlString;//html字符串
    private Document document;//html文档对象
    private StringBuilder contents;// html 内容
    private List<Table> tables;// html 表格信息


    public void setDocument(Document document) {
        this.document = document;
        this.initContent(); // 从上到下依次读取内容
    }

    private void initContent() {
        Elements children = document.body().children();
        this.contents = new StringBuilder();
        this.tables = new ArrayList<>();
        this.traverseElements(children,contents,tables);
        super.setContent(this.contents.toString());
        super.setOcrPages(Collections.singletonMap(1,this.tables));
    }

    private void traverseElements(Elements elements,StringBuilder contents,List<Table> tables) {
        for (Element element : elements) {
            Table table = null;
            List<Line> lines = new ArrayList<>(0);
            List<Cell> tableCells = new LinkedList<>();
            switch (element.tagName()) {
                case "h1":
                case "h2":
                case "h3":
                case "h4":
                case "h5":
                case "p":
                case "span":
                    if(StrUtil.isBlank(element.text())){
                        continue;
                    }
                    contents.append(element.text()).append("\n");
                    if(CollUtil.isNotEmpty(tables)){
                        int index = tables.size() - 1;
                        Table tb = tables.get(index);
                        List<Line> l = tb.getLines();
                        List<Cell> t = tb.getTableCells();
                        if(CollUtil.isNotEmpty(l) && CollUtil.isEmpty(t)){
                            lines = l;
                        }else if(CollUtil.isNotEmpty(t) && CollUtil.isEmpty(l)){
                            table = getTable(PLAIN,lines,tableCells);
                        }
                    }else{
                        table = getTable(PLAIN,lines,tableCells);
                    }
                    Line line = Line.builder().type(ExcelOcrTypeEnum.TEXT.type()).text(element.text()).build();
                    lines.add(line);
                    if(table != null){
                        tables.add(table);
                    }
                    break;
                case "table":
                    element.select("tr").forEach(row -> contents.append(row.text()).append("\n"));
                    if(CollUtil.isNotEmpty(tables)){
                        int index = tables.size() - 1;
                        Table tb = tables.get(index);
                        List<Line> l = tb.getLines();
                        List<Cell> t = tb.getTableCells();
                        if(CollUtil.isNotEmpty(t) && CollUtil.isEmpty(l)){
                            tableCells = t;
                        }else if(CollUtil.isNotEmpty(l) && CollUtil.isEmpty(t)){
                            table = getTable(TABLE_WITH_LINE, lines, tableCells);
                        }
                    }else{
                        table = getTable(TABLE_WITH_LINE, lines, tableCells);
                    }
                    parseTable(element,tableCells);
                    if(table != null){
                        tables.add(table);
                    }
                    break;
                case "img":
                    System.out.println("Image: " + element.attr("src"));
                    break;
                default:
                    // 递归处理子元素
                    traverseElements(element.children(),contents,tables);
                    break;
            }
        }
    }

    private Table getTable(ExcelOcrTypeEnum ocrType, List<Line> lines, List<Cell> tableCells) {
        return Table.builder()
                .type(ocrType.type())
                .pageNumber(1)
                .lines(lines)
                .tableCells(tableCells)
                .manager(super.getManager())
                .accessId(super.getId())
                .build();
    }

    private static void parseTable(Element table,List<Cell> tableCells) {
        Elements rows = table.select("tr");
        int rowCount = rows.size();
        int colCount = rows.stream().mapToInt(row -> row.select("td, th").size()).max().orElse(0);

        for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
            Element row = rows.get(rowIndex);
            Elements cells = row.select("td, th");
            for (int colIndex = 0; colIndex < cells.size(); colIndex++) {
                Element cell = cells.get(colIndex);
                int rowspan = cell.attr("rowspan").isEmpty() ? 1 : Integer.parseInt(cell.attr("rowspan"));
                int colspan = cell.attr("colspan").isEmpty() ? 1 : Integer.parseInt(cell.attr("colspan"));

                // 计算合并单元格的坐标
                int startRow = rowIndex;
                int endRow = startRow + rowspan - 1;
                int startCol = colIndex;
                int endCol = startCol + colspan - 1;

                // 输出单元格的坐标和合并信息
                System.out.println("Cell (" + startRow + ", " + endRow + ", "+ startCol+ ", " +  endCol +"): " + cell.text());
                Cell ce = Cell.builder().isHeader(0).startRow(startRow).endRow(endRow).startCol(startCol).endCol(endCol).text(cell.text()).build();
                tableCells.add(ce);
                if (rowspan > 1 || colspan > 1) {
                    System.out.println("  Merged: (" + startRow + ", " + endRow + ", " + startCol + ", " + endCol + ")");
                }
            }
        }
    }
}